﻿using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading;
using RpcClient.Config;
using RpcClient.Config.Model;
using RpcClient.Helper;
using RpcClient.Model;
using RpcClient.RpcApi;
using RpcHelper;
using RpcHelper.TaskTools;
using RpcModel;
using RpcModel.Server;

namespace RpcClient.Collect
{
    internal class RpcStateCollect
    {
        private static readonly Process _Process = null;
        private static volatile bool _IsInit = false;
        private static LocalRpcConfig _LocalConfig;
        private static MsgSource _Source;
        public static long RpcMerId
        {
            get;
            private set;
        }
        public static RpcConfig OAuthConfig { get; private set; }
        public static RpcServerConfig ServerConfig { get; private set; }
        public static MsgSource LocalSource => _Source;
        public static LocalRpcConfig LocalConfig =>_LocalConfig;
        public static long ServerId { get; private set; }
        public static bool IsInit => _IsInit;

        static RpcStateCollect()
        {
            _Process = Process.GetCurrentProcess();
            TaskManage.AddTask(new TaskHelper("同步服务状态!", new TimeSpan(0, 1, 0), new Action(_SyncSysState)));
        }

        private static void _SyncSysState()
        {
            if (_IsInit)
            {
                ServiceHeartbeat obj = new ServiceHeartbeat
                {
                    ServerId = RpcStateCollect.ServerId,
                    RunState = _GetRunState(),
                    RemoteState = RemoteServerCollect.GetRemoteState()
                };
                RpcServiceApi.SendHeartbeat(obj);
            }
        }

        public static bool InitServer(out string error)
        {
            if (_IsInit)
            {
                error = null;
                return true;
            }
            else if (!RpcTokenCollect.GetAccessToken(out RpcToken token, out error))
            {
                return false;
            }
            else
            {
                RemoteServerLogin login = new RemoteServerLogin
                {
                    SystemType = WebConfig.RpcSystemType,
                    ServerMac = WebConfig.Environment.Mac,
                    ServerIndex = WebConfig.RpcServerIndex,
                    ContainerType = WebConfig.RpcConfig.ContainerType,
                    Process = new ProcessDatum
                    {
                        Pid = _Process.Id,
                        PName = _Process.ProcessName,
                        MachineName = _Process.MachineName,
                        StartTime = _Process.StartTime,
                        WorkMemory = _Process.WorkingSet64,
                        Framework = RuntimeInformation.FrameworkDescription,
                        OSArchitecture= RuntimeInformation.OSArchitecture,
                        OSDescription= RuntimeInformation.OSDescription,
                        ProcessArchitecture= RuntimeInformation.ProcessArchitecture,
                        RuntimeIdentifier= RuntimeInformation.RuntimeIdentifier,
                        RunIsAdmin= WebConfig.Environment.RunIsAdmin,
                        RunUserGroups =Tools.GetRunUserGroups(),
                        RunUserIdentity= WebConfig.Environment.RunUserIdentity,
                        OSType=Tools.GetOSType()
                    }
                };
                RpcSysConfig sysConfig = WebConfig.RpcConfig;
                if (sysConfig.ContainerType != ContainerType.无)
                {
                    login.Container = new ContainerInfo
                    {
                        DefPort = sysConfig.DefPort,
                        ContainerId = ContainerHelper.ContainerId()
                    };
                }
                if (!DataValidateHepler.ValidateData(login, out error))
                {
                    return false;
                }
                else if (!RpcServiceApi.ServerLogin(token, login, out RpcConfig config, out RpcServerConfig serverConfig, out error))
                {
                    return false;
                }
                else
                {
                    _IsInit = true;
                    RpcMerId = token.RpcMerId;
                    ServerId = serverConfig.ServerId;
                    OAuthConfig = config;
                    ServerConfig = serverConfig;
                    _LocalConfig = new LocalRpcConfig
                    {
                        RegionId = serverConfig.RegionId,
                        SysGroup = serverConfig.GroupTypeVal,
                        SysGroupId = ServerConfig.GroupId,
                        SystemTypeId = ServerConfig.SystemType,
                        ServerId = serverConfig.ServerId,
                        SystemType = WebConfig.RpcSystemType,
                        RpcMerId = token.RpcMerId,
                        ApiVer = serverConfig.VerNum
                    };
                    _Source = _LocalConfig.ConvertMap<LocalRpcConfig, MsgSource>();
                    return true;
                }
            }
        }

        private static RunState _GetRunState()
        {
            _Process.Refresh();
            return new RunState
            {
                LockContentionCount = Monitor.LockContentionCount,
                ConNum = SocketTcpServer.SocketTcpServer.GetSocketClientNum(SocketTcpServer.SocketTcpServer.DefaultServerId),
                WorkMemory = _Process.WorkingSet64,
                CpuRunTime = (int)_Process.TotalProcessorTime.TotalMilliseconds,
                GCBody = GCHelper.GetGC(),
                ThreadNum = _Process.Threads.Count
            };
        }

        public static void Close()
        {
            _Process.Dispose();
        }

    }
}
